﻿#include "log_helper.h"
#include <QMutex>
#include <iostream>
#include <QDateTime>
#include <QCoreApplication>
#include <QFile>
#include <QDir>
#include <QTextStream>  
#include "QDebug"



static QMutex mutex;
//MyLog myLog;

void customMessageHandler(QtMsgType type,
	const QMessageLogContext& context,
	const QString& msg)
{
	//Q_UNUSED(context)
	QDateTime _datetime = QDateTime::currentDateTime();
	QString szDate = _datetime.toString("yyyy-MM-dd hh:mm:ss.zzz");//"yyyy-MM-dd hh:mm:ss ddd"
	QString txt(szDate);

	switch (type)
	{
	case QtDebugMsg://调试信息提示
	{
		txt += QString(" [Debug] ");
		break;
	}
	case QtInfoMsg://信息输出
	{
		txt += QString(" [Info] ");
		break;
	}
	case QtWarningMsg://一般的warning提示
	{
		txt += QString(" [Warning] ");
		break;
	}
	case QtCriticalMsg://严重错误提示
	{
		txt += QString(" [Critical] ");
		break;
	}
	case QtFatalMsg://致命错误提示
	{
		txt += QString(" [Fatal] ");
		//abort();
		break;
	}
	default:
	{
		txt += QString(" [Trace] ");
		break;
	}
	}

	txt.append(QString(" %1").arg(context.file));
	txt.append(QString("<%1>: ").arg(context.line));
	txt.append(msg);

	qInfo() << msg;

	mutex.lock();
	QFile file("log.txt");
	file.open(QIODevice::WriteOnly | QIODevice::Append);
	QTextStream text_stream(&file);
	text_stream << txt << "\r\n";
	file.close();
	mutex.unlock();
}

//接收调试信息的函数
void LogHelper::outputMessage(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
	static QMutex mutex;
	QMutexLocker lock(&mutex);

	QString text;
	switch (type)
	{
		//如果是debug信息，那么直接打印至应用程序输出，然后退出本函数
	case QtDebugMsg:
		//  std::cout << msg.toStdString() << std::endl;
		text = QString("[Debug]");
		break;
	case QtInfoMsg:
		text = QString("[Info]");
		break;
		//如果是警告，或者是下面的其他消息，则继续执行后面的数据处理
	case QtWarningMsg:
		text = QString("[Warning]");
		break;

	case QtCriticalMsg:
		text = QString("[Critical]");
		break;

	case QtFatalMsg:
		text = QString("[Fatal]...");
		break;

	default:
		text = QString("[Default].");
		break;
	}
	//获取单例
    LogHelper* myLog = LogHelper::Instance();


	outputTxtMsg(context, msg, text);
	outputHtmlMsg(context, msg, text);

}
void LogHelper::outputHtmlMsg(const QMessageLogContext& context, const  QString& msg, QString  text)
{
	QString fileName;
	QFileInfo fi(context.file);
	if (fi.exists())
		fileName = fi.absoluteFilePath();
	else
		fileName = context.file;

	//消息输出位置
	QString context_info = QString("[File]: <a href = \'%1 %2\'><font color = white> %1 %2</font>< /a>\r\n[Func]: %3")
		.arg(fileName)
		.arg(context.line)
		.arg(QString(context.function));

	//获取单例
    LogHelper* myLog = LogHelper::Instance();
	//////////////////////////////////////////////////////////////////////////
// 输出 html
	//消息打印时间
	QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
	QString current_date = QString("[Time]: %1").arg(current_date_time);

	QString msgHtml = msg;
	msgHtml.replace("  ", "&nbsp;");
	msgHtml.remove("\r");
	msgHtml.replace("\n", "<br>");
	msgHtml = QString("<font color=red>" + msgHtml + "</font>");

	//log 位置
	QString logPahtHtml = "<a href = \"%1\"><font color=white>%2</font></a>\r\n";
	logPahtHtml = logPahtHtml.arg(QCoreApplication::applicationDirPath() + "/" + myLog->logPath())
		.arg(msgHtml);
	//将调试信息格式化成 html 格式，

	QString contextInfoHtml = context_info;
	contextInfoHtml.remove("\r");
	contextInfoHtml.replace("\n", "<br>");
	//格式化后的调试信息
	QString messageHtml = QString("%1 %2<br>%3<br>")
		.arg(text)
		.arg(msgHtml)//.arg(logPahtHtml)
		.arg(current_date);


	//#ifdef _DEBUG
	messageHtml += contextInfoHtml;
	messageHtml += QString(" <br><br>");
	//#endif     

	QFile file_htm(myLog->logPath() + myLog->logHtmlName());
	file_htm.open(QIODevice::WriteOnly | QIODevice::Append);
	QTextStream html_stream(&file_htm);
	html_stream << messageHtml << "\r\n\r\n\r\n";
	file_htm.flush();
	file_htm.close();
	//////////////////////////////////////////////////////////////////////////
	//将处理成 html 的调试信息发送出去
	emit     myLog->sigDebugHtmlData(messageHtml);
}
void LogHelper::outputTxtMsg(const QMessageLogContext& context, const  QString& msg, QString  text)
{
	//消息输出位置
	QString context_info = QString("[File]: %1\r\n[Line]: %3\r\n[Func]: %2")
		.arg(QString(context.file))
		.arg(QString(context.function))
		.arg(context.line);

	//获取单例
    LogHelper* myLog = LogHelper::Instance();

	//消息打印时间
	QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ");
	QString current_date = QString("[Time]: %1").arg(current_date_time);
	//调试信息
	QString message = QString("%1%2:%3")
		.arg(text).arg(current_date_time)//.arg(current_date)
		.arg(": " + msg);
#ifdef _DEBUG
	//  message += QString("%1\r\n").arg(context_info);
#endif

	//将调试信息写入文件
	QFile file_txt(myLog->logPath() + myLog->logTextName());
	file_txt.open(QIODevice::WriteOnly | QIODevice::Append);
	QTextStream text_stream(&file_txt);
	text_stream << message << "\r\n";
	file_txt.flush();
	file_txt.close();

	//将处理好的调试信息发送出去
	emit   myLog->sigDebugStrData(message);
	//检查文件是否达到了指定大小
	if (file_txt.size() < 1024 * 1024) {
		return;
	}
	//log达到了限制值则将名字更改，防止文件越来越大
	for (int loop = 1; loop < 100; ++loop) {
		QString fileName = QString("%1/log_%2.txt").arg(myLog->logPath()).arg(loop);
		QFile file_1(fileName);
		if (file_1.size() < 4) {
			file_txt.rename(fileName);
			return;
		}
	}
}

//MyLog单例
LogHelper* LogHelper::self = nullptr;
LogHelper* LogHelper::Instance()
{
	if (!self)
	{
		static QMutex muter;
		QMutexLocker clocker(&muter);

		if (!self)
		{
            self = new LogHelper();
			self->installMessageHandler();
		}
	}
	return self;
}

//安装消息器
void LogHelper::installMessageHandler()
{
	//  QtMessageHandler msgHandler = (QtMessageHandler)outputMessage;
	qInstallMessageHandler(outputMessage);
}

//卸载消息器
void LogHelper::uninstallMessageHandler()
{
	qInstallMessageHandler(0);
}

//建立文件路径
QString LogHelper::logPath()
{
	QString current_date_file_name = QDateTime::currentDateTime().toString("yyyy-MM-dd");
	QDir dir(QString("log/%1").arg(current_date_file_name));
	if (!dir.exists()) {
		dir.mkpath("./");
	}
	return dir.path() + "/";
}

QString LogHelper::logTextName()
{
	return "log.txt";
}

QString LogHelper::logHtmlName()
{
	return "log.html";
}

LogHelper::LogHelper() {
	if (!self)
	{
		self = this;
		self->installMessageHandler();
	}
}

LogHelper::LogHelper(QObject* parent) : QObject(parent)
{
    static LogHelper::GC gc;
}

LogHelper::~LogHelper()
{
	std::cout << "~MyLog" << std::endl;

}

//垃圾自动回收
LogHelper::GC::~GC()
{
	if (self != nullptr) {
		delete self;
		self = nullptr;
	}
}
